#import "RNListContainerCell.h"
#import "RNConstants.h"
#import "NSShadow+MCAdditions.h"

static NSUInteger const titlePadding = 5;
NSUInteger RNListCategoryCellHighlightPadding = 2;
static NSColor *highlightBorderColor, *highlightFillColor;

@implementation RNListContainerCell

@synthesize mouseIsHovering = mouseIsHovering_;
@synthesize titleAttributesNormal = titleAttributesNormal_;
@synthesize titleAttributesHover = titleAttributesHover_;

+(void)initialize {
    highlightBorderColor = [NSColor colorWithCalibratedRed:0.0f green:0.373f blue:0.89f alpha:1.0f];
    highlightFillColor = [NSColor colorWithCalibratedRed:0.675f green:0.769f blue:0.898f alpha:0.75f];
}

-(id)initTextCell:(NSString *)title {
    if (!(self = [super initTextCell:title]))
        return nil;
    
    [self setAlignment:NSCenterTextAlignment];
    [self setDrawsBackground:NO];
    return self;
}


#pragma mark -
#pragma mark Accessors

-(BOOL)isEditable {
    return NO;
}

-(BOOL)isSelectable {
    return NO;
}

-(void)setObjectValue:(id)obj {
    if (![obj isKindOfClass:[NSDictionary class]])
        return;
    [super setObjectValue:[obj valueForKey:RNTitleKey]];
}

-(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    if ([self tag] != RNDragDropTagHighlighted) {
        [[self attributedStringValue] drawInRect:[self titleRectForBounds:cellFrame]];
        return;
    }
    NSBezierPath *highlightPath = [NSBezierPath bezierPathWithRoundedRect:[self highlightFrameForBounds:cellFrame] xRadius:RNDetailViewCellCornerRadius yRadius:RNDetailViewCellCornerRadius];
    [highlightBorderColor setStroke];
    [highlightPath setLineWidth:2.0f];
    [highlightPath stroke];
    [highlightFillColor setFill];
    [highlightPath fill];
    [[self attributedStringValue] drawInRect:[self titleRectForBounds:cellFrame]];
}


#pragma mark -
#pragma mark Accessors

-(NSDictionary *)titleAttributesNormal {
    if (!titleAttributesNormal_) {
        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
        [attributes setValue:[NSFont systemFontOfSize:12.0f] forKey:NSFontAttributeName];
        [attributes setValue:[NSColor colorWithCalibratedWhite:0.35f alpha:1.0f] forKey:NSForegroundColorAttributeName];
        NSColor *shadowColor = [NSColor colorWithCalibratedWhite:0.87f alpha:1.0f];
        NSShadow *textShadow = [[NSShadow alloc] initWithColor:shadowColor offset:NSMakeSize(0, -1) blurRadius:1];
        [attributes setValue:textShadow forKey:NSShadowAttributeName];
        titleAttributesNormal_ = (NSDictionary *)attributes;
    }
    return titleAttributesNormal_;
}

-(NSDictionary *)titleAttributesHover {
    if (!titleAttributesHover_) {
        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
        [attributes setValue:[NSFont systemFontOfSize:12.0f] forKey:NSFontAttributeName];
        [attributes setValue:[NSColor colorWithCalibratedWhite:0.35f alpha:1.0f] forKey:NSForegroundColorAttributeName];
        NSColor *shadowColor = [NSColor colorWithCalibratedWhite:0.87f alpha:1.0f];
        NSShadow *textShadow = [[NSShadow alloc] initWithColor:shadowColor offset:NSMakeSize(0, -1) blurRadius:1];
        [attributes setValue:textShadow forKey:NSShadowAttributeName];
        [attributes setValue:[NSNumber numberWithInteger:NSUnderlineStyleSingle | NSUnderlinePatternSolid] forKey:NSUnderlineStyleAttributeName];
        titleAttributesHover_ = (NSDictionary *)attributes;
    }
    return titleAttributesHover_;
}

-(NSRect)titleRectForBounds:(NSRect)cellFrame {
    NSAttributedString *title = [[NSAttributedString alloc] initWithString:[self stringValue] attributes:[self titleAttributesNormal]];
    NSSize titleSize = [title size];
    NSRect titleRect = NSInsetRect(cellFrame, (NSWidth(cellFrame) - titleSize.width) / 2, 0);
    titleRect.origin.y += NSHeight(cellFrame) - titleSize.height - titlePadding;
    titleRect.size.height = [title size].height;
    return titleRect;
}

-(NSRect)highlightFrameForBounds:(NSRect)cellFrame {
    NSRect titleFrame = [self titleRectForBounds:cellFrame];
    NSRect highlightFrame = NSInsetRect(cellFrame, RNListCategoryCellHighlightPadding, 0);
    highlightFrame.origin.y = NSMinY(titleFrame) - (4 * RNListCategoryCellHighlightPadding);
    highlightFrame.size.height = NSHeight(titleFrame) + (5 * RNListCategoryCellHighlightPadding);
    return highlightFrame;
}

- (NSAttributedString *)attributedStringValue {
    return [[NSAttributedString alloc] initWithString:[self stringValue] attributes:([self mouseIsHovering] ? [self titleAttributesHover] : [self titleAttributesNormal])];
}


#pragma mark -
#pragma mark Tracking methods

- (void)addTrackingAreasForView:(NSView *)controlView inRect:(NSRect)cellFrame withUserInfo:(NSDictionary *)userInfo mouseLocation:(NSPoint)currentPoint {
    NSRect titleFrame = [self titleRectForBounds:cellFrame];
    NSTrackingAreaOptions options = NSTrackingEnabledDuringMouseDrag | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways;
    NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:titleFrame options:options owner:controlView userInfo:userInfo];
    [controlView addTrackingArea:area];
}

- (void)mouseEntered:(NSEvent *)event {
    [self setMouseIsHovering:YES];
    [(NSControl *)[self controlView] updateCell:self];
}

- (void)mouseExited:(NSEvent *)event {
    [self setMouseIsHovering:NO];
    [(NSControl *)[self controlView] updateCell:self];
}

- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
    NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
    if ([controlView mouse:point inRect:[self titleRectForBounds:cellFrame]]) {
        return NSCellHitContentArea | NSCellHitTrackableArea;
    }
    return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
}

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp {
    NSRect titleRect = [self titleRectForBounds:cellFrame];
    while ([theEvent type] != NSLeftMouseUp) {
        NSPoint eventPoint = [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
        [self setMouseIsHovering:[controlView mouse:eventPoint inRect:titleRect]];
        if ([theEvent type] == NSMouseEntered || [theEvent type] == NSMouseExited) 
            [NSApp sendEvent:theEvent];
        theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseEnteredMask | NSMouseExitedMask)];
    }

    if ([self mouseIsHovering]) {
        [NSApp sendAction:[self action] to:[self target] from:self];
        [(NSControl *)[self controlView] updateCell:self];
    }
    return YES;
}

@end
